#pragma once

#include "connection/connection.h"

namespace umtl
{
	//////////////////////////////////////////////////////////////////////////
	//

	template< typename protocol >
	class server
	{
	public:
		typedef protocol protocol;
		typedef connection< protocol > connection;
		typedef typename connection::read_handler_t read_handler_t;
		typedef typename connection::close_handler_t close_handler_t;
		typedef connections< protocol > connectionProxy;
		typedef typename connectionProxy::type connections;

		server( unsigned short int port
			, read_handler_t read_handler
			, close_handler_t close_handler 
		)
			: port_(port)
			, read_handler_( read_handler )
		{
			close_handler_ = [this, close_handler]( connection * conn ) {
				close_handler( conn );
				{
					lock_section( connection_ct_ );
					auto iter = connections_.find( conn );
					if( iter != connections_.end() )
						connections_.erase(iter);
				}				
			};
		}

		int port() { return port_; }

		void send( char const * data, size_t len )
		{
			if( !data || !len )
				return;

			lock_section( connection_ct_ );

			std::for_each( connections_.begin(), connections_.end(),
				[data, len]( connections::value_type & conn )
				{
					conn.second->send( data, len );
				}
			);
		}

		connectionProxy getConnections() { return connectionProxy( connections_, connection_ct_ ); }

	protected:

		void insertConnection( connection * conn ) {
			if( conn )
			{
				lock_section(connection_ct_);
				connections_.insert( std::make_pair( conn, conn ) );
			}
		}

		unsigned short int port_;
		read_handler_t read_handler_;
		close_handler_t close_handler_;

		connections connections_;
		parallel::critical_section connection_ct_;

		parallel::thread accept_thread_;
	};

	//////////////////////////////////////////////////////////////////////////
}